#!/usr/bin/perl
use strict;
use Getopt::Long;
use JNPR::Utils;

my $opts = {};
GetOptions ($opts, 'db=s', 'svnroot=s');
my ($S, $db);
if (!exists $opts->{'svnroot'}) {
    die "Error: $0 : need svnroot\n";
}
if (!exists $opts->{'db'}) {
    die "Error: $0 : need db\n";
}
$S = $opts->{'svnroot'};
$db = $opts->{db};

my $g_sql_out = [];
JNPR::Utils::set_url($S);
JNPR::Utils::mk_tables($db);





dig_remaining_versions_for_branches();


#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub dig_remaining_versions_for_branches
{
    my ($branches_hi_rev, $branches_lo_rev)
           = JNPR::Utils::get_counts($db, 'branches_hi_rev', 'branches_lo_rev');
    if ($branches_hi_rev == -1 and $branches_lo_rev == -1) {
        my ($svn_hi_rev, $svn_lo_rev)
               = JNPR::Utils::get_counts($db, 'svn_hi_rev', 'svn_lo_rev');
        my $dig_success;
        my $v = $svn_hi_rev;
        my ($done_hi, $done_lo) = (-1, -1);
        while (1) {
            $dig_success = dig_version_for_branch($v);
            last if (!$dig_success);
            if ($done_hi == -1 or $done_hi < $v) {
                $done_hi = $v;
            }
            if ($done_lo == -1 or $v < $done_lo) {
                $done_lo = $v;
            }
            if (-e 'kill') {
                unlink 'kill';
                JNPR::Utils::set_counts($db, 'branches_hi_rev', $done_hi);
                JNPR::Utils::set_counts($db, 'branches_lo_rev', $done_lo);
                flush2db();
                exit;
            }
            $v--;
        }
        JNPR::Utils::set_counts($db, 'branches_hi_rev', $done_hi);
        JNPR::Utils::set_counts($db, 'branches_lo_rev', $done_lo);
        flush2db();
    }
    else {
        my ($done_hi, $done_lo) = ($branches_hi_rev, $branches_lo_rev);
        my $dig_success;
        # Upward
        {
            my $v = $branches_hi_rev + 1;
            while (1) {
                $dig_success = dig_version_for_branch($v);
                last if (!$dig_success);
                $done_hi = $v;
                if (-e 'kill') {
                    unlink 'kill';
                    JNPR::Utils::set_counts($db, 'branches_hi_rev', $done_hi);
                    flush2db();
                    exit;
                }
                $v++;
            }
            JNPR::Utils::set_counts($db, 'branches_hi_rev', $done_hi);
            flush2db();
        }
        # Downward
        {
            my $v = $branches_lo_rev - 1;
            while (1) {
                $dig_success = dig_version_for_branch($v);
                last if (!$dig_success);
                $done_lo = $v;
                if (-e 'kill') {
                    unlink 'kill';
                    JNPR::Utils::set_counts($db, 'branches_lo_rev', $done_lo);
                    flush2db();
                    exit;
                }
                $v--;
            }
            JNPR::Utils::set_counts($db, 'branches_lo_rev', $done_lo);
            flush2db();
        }
    }
}


#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub dig_version_for_branch
{
    my ($r) = @_;

    # % cat -n 83/446483-rlog.txt
    # 0  ------------------------------------------------------------------------
    # 1  r446483 | sparasar | 2011-06-06 17:13:33 -0700 (Mon, 06 Jun 2011) | 10 lines
    # 2  Changed paths:
    # 3     A /branches/DEV_MOBILE_DIABLO_MAINT_BRANCH (from /branches/DEV_MOBILE_DIABLO_BRANCH:446044)
    # 4  

    my ($d) = "00$r" =~ /(..)$/;
    return 0 if (!-e "$d/${r}-rlog.txt");
    return 1 if (!-e "$d/${r}-branched.txt");

    my @rlog;

    open F, "<$d/${r}-rlog.txt" or die "$!: $d/${r}-rlog.txt";
    @rlog = <F>;
    close F;
    my $node_detail     = JNPR::Utils::grok_rlog(\@rlog);
    my $branch          = $node_detail->{branch};
    my $r               = $node_detail->{rev};
    my $parentbranch    = $node_detail->{parent_branch};
    my $parentrev       = $node_detail->{parent_rev};
    my $parent_rev_real = JNPR::Utils::get_real_rev($db, $parentbranch, $parentrev);

    my $cmd;
    $cmd = "INSERT INTO branches"
         . " (branch_name, creation_rev, parent_branch_name, parent_branch_rev)"
         . " VALUES "
         . " ('$branch', $r, '$parentbranch', $parent_rev_real);\n"
         ;
    push2db($cmd);
    return 1;
}

{
my $init;
my @cmds;
sub push2db
{
    unless (defined $init) {
        @cmds = ();
        $init = 'done';
    }

    push @cmds, @_;
    if (scalar @cmds == 30) {
        flush2db();
    }
}

sub flush2db
{
    unless (defined $init) {
        @cmds = ();
        $init = 'done';
    }

    if (scalar @cmds) {
        unshift @cmds, "BEGIN TRANSACTION;\n";
        push    @cmds, "COMMIT;\n";
        my $sql_query = join '', @cmds;

        JNPR::Utils::sql_query($db, \$sql_query, $g_sql_out);
        @cmds = ();
    }
}
}

sub get_rev_on_branch
{
    my ($path_with_rev) = @_;
    # https://svl-svn.juniper.net/svn/junos-2009/branches/somebranch@2345
    my ($branch, $input_rev) = $path_with_rev =~ m{([^/]+)\@(\d+)$};
    # somebranch, 2345
    my $cmd = "SELECT max(rev) FROM nodes WHERE branch=\"$branch\" AND rev <= $input_rev;\n";
    JNPR::Utils::sql_query($db, \$cmd, $g_sql_out);
    my $rev = $g_sql_out->[0];
    chomp $rev;
    return $rev;
}
